package com.fubowen.lepton.extension

import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream
import java.security.MessageDigest
import javax.crypto.Cipher
import javax.crypto.spec.SecretKeySpec


fun String.digest(): String {
    val passwordByte = this.toByteArray()
    val messageDigest = MessageDigest.getInstance("SHA-256")
    val password256 = messageDigest.digest(passwordByte)
    return password256.toString(Charsets.UTF_8)
}

fun String.encrypt(password: String): ByteArray {

    val passwordByte = password.toByteArray()
    val messageDigest = MessageDigest.getInstance("SHA-256")
    val password256 = messageDigest.digest(passwordByte)
    val spec = SecretKeySpec(password256, "AES")

    val cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING")
    cipher.init(Cipher.ENCRYPT_MODE, spec)

    return cipher.doFinal(this.toByteArray(Charsets.UTF_8))
}

fun ByteArray.decrypt(password: String): String {

    val passwordByte = password.toByteArray()
    val messageDigest = MessageDigest.getInstance("SHA-256")
    val password256 = messageDigest.digest(passwordByte)
    val spec = SecretKeySpec(password256, "AES")

    val cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING")
    cipher.init(Cipher.DECRYPT_MODE, spec)

    return cipher.doFinal(this).toString(Charsets.UTF_8)
}


fun File.encrypt(password: String, outputFile: File) {
    val cipher = Cipher.getInstance("AES/ECB/PKCS5Padding")
    val secretKeySpec = SecretKeySpec(password.toByteArray(Charsets.UTF_8), "AES")
    cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec)
    val inputStream = FileInputStream(this)
    val outputStream = FileOutputStream(outputFile)
    val buffer = ByteArray(8192)
    while (inputStream.read(buffer) != -1) {
        val outputBytes = cipher.update(buffer)
        outputStream.write(outputBytes)
    }
    val outputBytes = cipher.doFinal()
    outputStream.write(outputBytes)
    inputStream.close()
    outputStream.close()
}

fun File.decrypt(password: String, outputFile: File) {
    val cipher = Cipher.getInstance("AES/ECB/PKCS5Padding")
    val secretKeySpec = SecretKeySpec(password.toByteArray(Charsets.UTF_8), "AES")
    cipher.init(Cipher.DECRYPT_MODE, secretKeySpec)
    val inputStream = FileInputStream(this)
    val outputStream = FileOutputStream(outputFile)
    val buffer = ByteArray(8192)
    while (inputStream.read(buffer) != -1) {
        val outputBytes = cipher.update(buffer)
        outputStream.write(outputBytes)
    }
    val outputBytes = cipher.doFinal()
    outputStream.write(outputBytes)
    inputStream.close()
    outputStream.close()
}

inline fun <T> T?.isNotNull(block: (T) -> Unit) {
    if (this != null) {
        block(this)
    }
}

inline fun <T> T?.isNull(block: () -> Unit) {
    if (this == null) {
        block()
    }
}

fun <T> T?.isNotNull(): Boolean {
    return this != null
}